﻿using RockBus.DataContracts;
using RockBus.Logging.Interfaces;
using RockBus.Messages.Interfaces;
using RockBus.ServiceModel;
using RockBus.Subscription.Interfaces;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace RockBus.Subscription.Evaluators
{
    public class TopicEvaluator : IEvaluator<SubscriberConfiguration>
    {
        public TopicEvaluator(ILogger logger)
        {
            this.Logger = logger;
            this.TopicSubscriptionDictionary = new ConcurrentDictionary<Regex, List<SubscriptionInfo>>();
        }

        private ILogger Logger { get; set; }

        private SubscriberConfiguration SubscriberConfiguration { get; set; }

        private ConcurrentDictionary<Regex, List<SubscriptionInfo>> TopicSubscriptionDictionary { get; set; }

        public void Initialize(SubscriberConfiguration subscriberConfiguration)
        {
            this.SubscriberConfiguration = subscriberConfiguration;
            this.BuildTopicFilterDictionary();
        }

        private void BuildTopicFilterDictionary()
        {
            IDictionary<string, List<SubscriptionInfo>> tempDict = new Dictionary<string, List<SubscriptionInfo>>();
            foreach (SubscriberInfo si in this.SubscriberConfiguration.EvaluationElementDictionary.Values.ToArray())
            {
                foreach (FilterInfo fi in si.FilterInfoDictionary.Values.ToArray())
                {
                    if (fi.FilterType == FilterTypeEnum.Topic)
                    {
                        if (!tempDict.ContainsKey(fi.FilterData))
                        {
                            tempDict.Add(fi.FilterData, new List<SubscriptionInfo>());
                        }

                        tempDict[fi.FilterData].AddRange(
                            si.InfoDictionary.Values.Where(si1 => si1.FilterIds.Contains(fi.Id)));
                    }
                }
            }

            this.TopicSubscriptionDictionary.Clear();
            foreach (var topicFilter in tempDict)
            {
                Regex regex = new Regex(topicFilter.Key, RegexOptions.None);
                this.TopicSubscriptionDictionary.TryAdd(regex, topicFilter.Value);
            }
        }

        public void Evaluate(IMessage messageWrapper, EvaluationResult evaluationResult)
        {
            object topicHeaderObj = messageWrapper.Properties.GetTopicHeader();
            if (null != topicHeaderObj)
            {
                TopicHeader topicHeader = topicHeaderObj as TopicHeader;
                evaluationResult.TopicInfoDictionary[topicHeader.TopicInfo.Name] = topicHeader.TopicInfo;
            }

            foreach (var topicSubscription in this.TopicSubscriptionDictionary.ToArray())
            {
                foreach (var topic in evaluationResult.TopicInfoDictionary)
                {
                    if (topicSubscription.Key.IsMatch(topic.Key))
                    {
                        evaluationResult.AddSubscriptions(topicSubscription.Value);
                    }
                }
            }

            // Lazy initialize the topic matrix

            // Evaluate message against topic matrix
        }
    }
}